import sys
!{sys.executable} -m pip install OWSLib==0.28.1

import owslib
from owslib.wfs import WebFeatureService
from owslib.ogcapi.features import Features
import geopandas as gpd
from datetime import datetime, timedelta

Look at the data that is availible through the Web Feature Service (WFS)

The datasets that are distributed throught the WFS are organized into collections. We can display the collections with the command:

w = Features(url = "https://pzh7fedpc0.execute-api.us-west-2.amazonaws.com") # Load base url of WFS

feature_collections = w.feature_collections()
feature_collections
['public.eis_fire_fireline',
 'public.eis_fire_newfirepix',
 'public.eis_fire_newfirepix_2',
 'public.eis_fire_perimeter',
 'public.st_hexagongrid',
 'public.st_squaregrid',
 'public.st_subdivide']

We will focus on the public.eis_fire_fireline collection and the public.eis_fire_perimeter collection.

Learn about the public.eis_fire_perimeter collection

We can access information thaat drescribes the public.eis_fire_perimeter.

perm = w.collection('public.eis_fire_perimeter')
print("Spatial extent: ", perm['extent']['spatial']['bbox']) # Coordinates of the spatial extent
print("Coordinate Reference System: ", perm['extent']['spatial']['crs']) 
print("Time range:", perm['extent']['temporal']['interval']) # Range of datetimes availible
Spatial extent:  [[-123.99217987060547, 31.054306030273438, -101.49222564697266, 49.461177825927734]]
Coordinate Reference System:  http://www.opengis.net/def/crs/EPSG/0/4326
Time range: [['2019-05-01T00:00:00+00:00', '2020-10-31T12:00:00+00:00']]
perm_q = w.collection_queryables('public.eis_fire_perimeter')
perm_cols = perm_q['properties']
perm_cols # Get perimeter columns and column types
{'wkb_geometry': {'$ref': 'https://geojson.org/schema/Geometry.json'},
 'meanfrp': {'name': 'meanfrp', 'type': 'number'},
 't': {'name': 't', 'type': 'string'},
 'fid': {'name': 'fid', 'type': 'number'},
 'pixden': {'name': 'pixden', 'type': 'number'},
 'duration': {'name': 'duration', 'type': 'number'},
 'flinelen': {'name': 'flinelen', 'type': 'number'},
 'fperim': {'name': 'fperim', 'type': 'number'},
 'farea': {'name': 'farea', 'type': 'number'},
 'n_newpixels': {'name': 'n_newpixels', 'type': 'number'},
 'n_pixels': {'name': 'n_pixels', 'type': 'number'},
 'ogc_fid': {'name': 'ogc_fid', 'type': 'number'}}

Contruct and API Query Read-in the Data

We will read the data into this notebook in two steps.

  1. Construct a url that points to the subset of the data we are interested in

  2. Read the data into a geopandas dataframe

To construct the url with pre-filtered data, we are using the owslib package. In the below example, we are reading in the public.eis_fire_perimetercollection , subsetting it by space using the bbox parameter, and subsetting it by time using the datetime.

The limit parameter desginated the maximum number of objects the query will return. The default limit is 10, so if we want to all of the fire perimeters within certain conditions, we need to make sure that the limit is large, and that the numberMatched is less than the limit.

The filter parameter lets us filter by the columns in the ‘public.eis_fire_perimeter’. Here we are filter for fires over 5km^2 and over 20 days long. filter supports SQL-style queries.

perm_results = w.collection_items(
    'public.eis_fire_perimeter',   # Name of the dataset we want
    bbox=['-119.5', '36.8', '-118.9', '37.7'], # Coodrinates of bounding box, 
    datetime=['2020-01-01T00:00:00+00:00/2020-10-31T12:00:00+00:00'], # Date range
    limit=1000,
    filter="farea>5 AND duration>20"
    
)

print(perm_results['numberMatched']) # Less than the limit
perm_results['links'][1]['href'] # The url query we constucted
125
'https://pzh7fedpc0.execute-api.us-west-2.amazonaws.com/collections/public.eis_fire_perimeter/items?bbox=-119.5%2C36.8%2C-118.9%2C37.7&datetime=2020-01-01T00%3A00%3A00%2B00%3A00%2F2020-10-31T12%3A00%3A00%2B00%3A00&limit=1000&filter=farea%3E5+AND+duration%3E20'
## Read in the filtered data to a GeoPandas DataFrame

df = gpd.GeoDataFrame.from_features(perm_results["features"])
df
geometry meanfrp t fid pixden duration flinelen fperim farea n_newpixels n_pixels ogc_fid
0 POLYGON ((-118.98956 37.14274, -118.98955 37.1... 0.000000 2020-10-24T00:00:00 6683 32.483377 30.5 0.000000 11.731364 7.326824 0 238 39758
1 POLYGON ((-118.98956 37.14274, -118.98955 37.1... 0.000000 2020-10-25T00:00:00 6683 32.483377 30.5 0.000000 11.731364 7.326824 0 238 39759
2 POLYGON ((-118.98956 37.14274, -118.98956 37.1... 0.000000 2020-10-08T12:00:00 6683 32.346892 29.5 0.000000 11.731364 7.326824 0 237 39760
3 POLYGON ((-118.98956 37.14274, -118.98956 37.1... 0.000000 2020-10-06T00:00:00 6683 32.210409 26.5 0.000000 11.731358 7.326824 0 236 39761
4 POLYGON ((-118.98956 37.14273, -118.98956 37.1... 0.580000 2020-10-03T00:00:00 6683 32.333326 24.5 0.000000 11.731136 7.268043 1 235 39762
... ... ... ... ... ... ... ... ... ... ... ... ...
120 POLYGON ((-119.43342 37.31364, -119.43343 37.3... 24.795108 2020-10-02T12:00:00 6280 19.811109 27.5 23.845096 270.752955 1453.780326 139 28801 40607
121 POLYGON ((-119.43342 37.31364, -119.43342 37.3... 2.427910 2020-10-02T00:00:00 6280 19.742769 27.0 32.202091 270.218766 1451.772072 335 28662 40608
122 POLYGON ((-119.43343 37.31364, -119.43343 37.3... 3.254313 2020-10-03T00:00:00 6280 19.916462 28.0 36.112503 274.300699 1461.805801 313 29114 40609
123 POLYGON ((-119.43343 37.31365, -119.43343 37.3... 19.402735 2020-10-03T12:00:00 6280 20.002112 28.5 34.356263 275.740728 1467.245064 234 29348 40610
124 POLYGON ((-119.43343 37.31365, -119.43343 37.3... 2.941368 2020-10-04T00:00:00 6280 20.107355 29.0 36.152268 277.331754 1475.927568 329 29677 40611

125 rows × 12 columns

df = df.set_crs("EPSG:4326")
df.t = df.t.astype("str")
df.explore()
Make this Notebook Trusted to load map: File -> Trust Notebook

Visualize Most Recent Fire Perimeters with Firelines

If we wanted to combine collections to make more informative analyses, we can use some of the same principles.

fline_q = w.collection_queryables('public.eis_fire_fireline')
fline_cols = fline_q['properties']
fline_cols
{'wkb_geometry': {'$ref': 'https://geojson.org/schema/Geometry.json'},
 'ogc_fid': {'name': 'ogc_fid', 'type': 'number'},
 'fid': {'name': 'fid', 'type': 'number'},
 't': {'name': 't', 'type': 'string'}}
## Get most recent fire perimeters

most_recent_time = max(*perm['extent']['temporal']['interval']) 
print("Most Recent Time =", most_recent_time)

    
perm_results = w.collection_items(
    'public.eis_fire_perimeter',   
    datetime = most_recent_time,
    limit=1000,
    filter="farea>5"
    
)

## Get the most recent fire lines
perimeters = gpd.GeoDataFrame.from_features(perm_results['features'])
perimeter_ids = perimeters.fid.unique()
perimeter_ids = ",".join(map(str, perimeter_ids)) 

fline_results = w.collection_items(
    'public.eis_fire_fireline',   
    datetime = most_recent_time,
    limit=1000,
    filter = "fid IN (" + perimeter_ids + ")" # only the fires from the fire perimeter query
    
)
fline = gpd.GeoDataFrame.from_features(fline_results['features'])
Most Recent Time = 2020-10-31T12:00:00+00:00
## Visualize together

perimeters.t = perimeters.t.astype("str")
perimeters = perimeters.set_crs("epsg:4326")
fline.t = fline.t.astype("str")
fline = fline.set_crs("epsg:4326")


m = perimeters.explore()
m = fline.explore(m = m, color = "orange")
m
Make this Notebook Trusted to load map: File -> Trust Notebook